package br.com.ponto.model;

import java.io.Serializable;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.Date;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;

/**
 * The persistent class for the Ponto database table.
 * 
 */
@Entity
public class Ponto extends Controle implements Serializable {
	private static final long serialVersionUID = 1L;
	
	@Id
	@GeneratedValue(strategy=GenerationType.AUTO)
	private Integer idPonto;
	
	//bi-directional many-to-one association to Funcionario
	@ManyToOne(fetch=FetchType.EAGER)
	@JoinColumn(name="idEmpresa", updatable=false)
	private Empresa empresa;
	
	//bi-directional many-to-one association to Funcionario
    @ManyToOne(fetch=FetchType.EAGER)
	@JoinColumn(name="idFuncionario", updatable=false)
	private Funcionario funcionario;
    
    private Double jornada;
	
	private Integer tolerancia;
	
    @Embedded
	private Competencia competencia;
	
	@Column(name="periodoInicio")
	private Date dataInicio;
	
	@Column(name="periodoFim")
	private Date dataFim;
	
	private Boolean ativo;
	
	//bi-directional many-to-one association to Funcionario
	@OneToMany(mappedBy="ponto", fetch=FetchType.LAZY, orphanRemoval=true, cascade={CascadeType.ALL})
	private List<Registro> registros;
	
	public Ponto() {
		this.ativo = Boolean.TRUE;
	}

	public Funcionario getFuncionario() {
		return funcionario;
	}

	public void setFuncionario(Funcionario funcionario) {
		this.funcionario = funcionario;
	}

	public Competencia getCompetencia() {
		return competencia;
	}

	public void setCompetencia(Competencia competencia) {
		this.competencia = competencia;
	}

	public Date getDataInicio() {
		return dataInicio;
	}

	public void setDataInicio(Date dataInicio) {
		this.dataInicio = dataInicio;
	}

	public Date getDataFim() {
		return dataFim;
	}

	public void setDataFim(Date dataFim) {
		this.dataFim = dataFim;
	}

	public List<Registro> getRegistros() {
		return registros;
	}

	public void setRegistros(List<Registro> registros) {
		this.registros = registros;
	}

	public Empresa getEmpresa() {
		return empresa;
	}

	public void setEmpresa(Empresa empresa) {
		this.empresa = empresa;
	}

	public Integer getIdPonto() {
		return idPonto;
	}

	public void setIdPonto(Integer idPonto) {
		this.idPonto = idPonto;
	}

	public Double getJornada() {
		return jornada;
	}

	public void setJornada(Double jornada) {
		this.jornada = jornada;
	}

	public Integer getTolerancia() {
		return tolerancia;
	}

	public void setTolerancia(Integer tolerancia) {
		this.tolerancia = tolerancia;
	}

	public Boolean getAtivo() {
		return ativo;
	}

	public void setAtivo(Boolean ativo) {
		this.ativo = ativo;
	}

	public String getJornadaTrabalhoHHMM() {
		if(this.jornada != null) {
			Double jornada = this.jornada * 60; // jornada em minutos
			int horas = jornada.intValue()/60;
			int minutos = jornada.intValue() % 60;
			
			NumberFormat nf = new DecimalFormat("00");
			
			return nf.format(horas) + ":" + nf.format(minutos);
		}
		
		return null;
	}
	
	public String getTotalHorasValidas() {
		if(this.registros != null && !this.registros.isEmpty()) {
			Long totalMinutosTrabalhados = 0L;
			for(Registro reg:this.registros) {
				Long minutosTrabalhados =  reg.getMinutosTrabalhados();
				if(minutosTrabalhados > 0) {
					totalMinutosTrabalhados += minutosTrabalhados;
				} else if (minutosTrabalhados < 0){
					return "ERRO";
				}
			}
			
			int horas = totalMinutosTrabalhados.intValue()/60;
			int minutos = totalMinutosTrabalhados.intValue() % 60;
			
			NumberFormat nf = new DecimalFormat("#00");
			
			return nf.format(horas) + ":" + nf.format(minutos);
		}
		
		return null;
	}
	
	public String getTotalHorasAtraso() {
		if(this.registros != null && !this.registros.isEmpty()) {
			Long totalMinutosTrabalhadosExtra = 0L;
			for(Registro reg:this.registros) {
				Long minutosTrabalhados = reg.getMinutosTrabalhados();
				
				if(minutosTrabalhados != null && minutosTrabalhados > 0) {
					Long minutosTrabalhadosExtra =  reg.getMinutosTrabalhadosExtra();
					
					if(minutosTrabalhadosExtra != null && minutosTrabalhadosExtra < 0) {
						totalMinutosTrabalhadosExtra += minutosTrabalhadosExtra;
					}
				} else if(minutosTrabalhados < 0) {
					return "ERRO";
				} else if(minutosTrabalhados == 0 && !(reg.isFeriado() || reg.isFimDeSemana())) {
					totalMinutosTrabalhadosExtra -= (long) (this.jornada*60);
				}
			}
			
			int horas = totalMinutosTrabalhadosExtra.intValue()/60;
			int minutos = totalMinutosTrabalhadosExtra.intValue() % 60;
			
			NumberFormat nf = new DecimalFormat("#00");
			
			return nf.format(Math.abs(horas)) + ":" + nf.format(Math.abs(minutos));
		}
		
		return null;
	}
	
	public String getTotalHorasExtra() {
		if(this.registros != null && !this.registros.isEmpty()) {
			Long totalMinutosTrabalhadosExtra = 0L;
			for(Registro reg:this.registros) {
				
				Long minutosTrabalhados = reg.getMinutosTrabalhados();
				
				if(minutosTrabalhados != null && minutosTrabalhados > 0) {
					Long minutosTrabalhadosExtra =  reg.getMinutosTrabalhadosExtra();
					
					if(minutosTrabalhadosExtra != null && minutosTrabalhadosExtra > 0) {
						totalMinutosTrabalhadosExtra += minutosTrabalhadosExtra;
					}
				} else if(minutosTrabalhados < 0) {
					return "ERRO";
				}
			}
			
			int horas = totalMinutosTrabalhadosExtra.intValue()/60;
			int minutos = totalMinutosTrabalhadosExtra.intValue() % 60;
			
			NumberFormat nf = new DecimalFormat("#00");
			
			return nf.format(horas) + ":" + nf.format(minutos);
		}
		
		return null;
	}
	
}
